﻿using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using KL.UFrame.Api.Extension;
using KL.UFrame.Core.Configuration;
using KL.UFrame.Core.Result;
using KL.UFrame.Data.Business.Account;
using KL.UFrame.Data.Models.Account;
using Microsoft.AspNet.Identity;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;

namespace KL.UFrame.Api.ApiControllers
{

    [RoutePrefix("api/Account")]
    public class AccountController : K9ApiBaseController
    {
        private IAccountBusiness _business;
        private IAuthenticationManager Authentication => Request.GetOwinContext().Authentication;

        public AccountController()
        {
        }

        public AccountController(IAccountBusiness business)
        {
            _business = business;
        }

        /// <summary>
        /// 注册新用户
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [Route("Register")]
        public async Task<ResultMessage> Register(UserRegisterModel model)
        {
            if (!ModelState.IsValid)
            {
                return ModelState.ToResultMessage();
            }
            var result = await _business.CreateUserAsync(model);
            return result ? new ResultMessage() : new ResultMessage(-500, "保存用户数据失败");
        }


        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <returns></returns>
        [Route("UserInfo")]
        public async Task<ResultMessage<UserInfoModel>> GetUserInfo()
        {
            var userInfo = await _business.GetUserInfoByNameAsync(User.Identity.Name);
            return new ResultMessage<UserInfoModel>(userInfo);
        }

        /// <summary>
        /// 用户注销
        /// </summary>
        /// <returns></returns>
        [AllowAnonymous]
        [Route("Logout")]
        public IHttpActionResult Logout()
        {
            try
            {
                Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType);
            }
            catch 
	        {
                //ignore
            }
            return Ok();
        }

        /// <summary>
        /// 找回密码
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [Route("SetPassword")]
        public async Task<ResultMessage> SetPassword(ResetPasswordModel model)
        {
            if (!ModelState.IsValid)
            {
                return ModelState.ToResultMessage();
            }
            var result = await _business.SetPassordAsync(model);
            return result ? new ResultMessage() : new ResultMessage(-500, "找回密码失败");
        }

        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [Route("ChangePassword")]
        public async Task<ResultMessage> ChangePassword(ChangePasswordModel model)
        {
            if (!ModelState.IsValid)
            {
                return ModelState.ToResultMessage();
            }
            model.UserName = User.Identity.Name;
            var result = await _business.ChangePassordAsync(model);
            return result ? new ResultMessage() : new ResultMessage(-500, "修改密码失败");
        }

        /// <summary>
        /// 获取用户余额
        /// </summary>
        /// <returns></returns>
        [Route("ChangeNickname")]
        public async Task<ResultMessage> ChangeNickname(string name)
        {
            if (!AppConfiguration.StringValidateRegex.IsMatch(name))
            {
                return new ResultMessage(-1, "昵称包含非法字符");
            }
            return new ResultMessage(await _business.ChangeNicknameAsync(User.Identity.GetUserId(), name));
        }

        #region 帮助程序

        private static class RandomOAuthStateGenerator
        {
            private static RandomNumberGenerator _random = new RNGCryptoServiceProvider();

            public static string Generate(int strengthInBits)
            {
                const int bitsPerByte = 8;

                if (strengthInBits % bitsPerByte != 0)
                {
                    throw new ArgumentException("strengthInBits 必须能被 8 整除。", nameof(strengthInBits));
                }

                int strengthInBytes = strengthInBits / bitsPerByte;

                byte[] data = new byte[strengthInBytes];
                _random.GetBytes(data);
                return HttpServerUtility.UrlTokenEncode(data);
            }
        }

        #endregion
    }
}
